﻿#pragma once
#include "yzrutil.h"
#include "TokenReader.h"
#include <sstream>
namespace yzrilyzr_ast{
	EBCLASS(ASTTokenizer){
	private:
	static constexpr const char defSkip[]={'\t', ' ', '\n', '\r'};
	static constexpr const char * symbols1[21]={
		"(",
		")",
		"=",
		"[",
		"]",
		",",
		".",
		"!",
		"~",
		"*",
		"/",
		"%",
		"+",
		"-",
		"<",
		">",
		"&",
		"^",
		"|",
		"?",
		":"};
	static constexpr const char * symbols2[19]={
		"++",
		"--",
		"<<",
		">>",
		"<=",
		">=",
		"==",
		"!=",
		"&&",
		"||",
		"+=",
		"-=",
		"*=",
		"/=",
		"%=",
		"&=",
		"|=",
		"^=",
		"~="
	};
	static constexpr const char * symbols3[2]={"<<=", ">>="};
	//static char[] skip=nullptr;
	public:
	static std::shared_ptr<TokenReader> tokenize(const yzrilyzr_lang::String & s);
	private:
	static bool isWord(char c){
		if((c | 0b100000) >= 'a' && (c | 0b100000) <= 'z') return true;
		if(c >= '0' && c <= '9') return true;
		if(c == '$') return true;
		if((int32_t)c >= 0x4e00 && (int32_t)c <= 0x9fa5) return true;
		return c == '_';
	}
	static bool isNumber(char c){
		if((c | 0b100000) >= 'a' && (c | 0b100000) <= 'z') return true;
		if(c >= '0' && c <= '9') return true;
		if(c == '$') return true;
		if(c == '_') return true;
		return c == '.';
	}
	/*static char[] getSkip(){
		if(skip==nullptr) return defSkip;
		return skip;
	}*/
	static std::string readSymbol(CharReader & reader, u_index w){
		const char * const * s1=nullptr;
		u_index length=0;
		if(w == 2){
			s1=symbols3;
			length=2;
		} else if(w == 1){
			s1=symbols2;
			length=19;
		} else if(w == 0){
			s1=symbols1;
			length=21;
		}
		std::stringstream sb;
		for(u_index j=0;j < w + 1;j++){
			sb << reader.get(j);
		}
		std::string s2(sb.str());
		for(u_index ii=0;ii < length;ii++){
			std::string s3((char *)s1[ii]);
			if(s2 == s3){
				for(u_index j=0;j < w + 1;j++){
					reader.next();
				}
				return s2;
			}
		}
		return "";
	}
	static std::string readSymbol(CharReader & reader){
		for(u_index i=yzrilyzr_lang::Math::min(reader.available() - 1, (u_index)2);i >= 0;i--){
			std::string str=readSymbol(reader, i);
			if(str.length() != 0)return str;
		}
		std::string s=std::to_string(reader.get());
		reader.next();
		return s;
	}
	/*public:
		static void setSkipChars(char[] skip1){
		skip=skip1;
	}*/
	/*private:
		static TokenizeException buildSyntaxError(String msg,CharReader reader){
		int pos=reader.index;
		String sb=new String();
		sb.append(msg).append(" '").append(reader.get()).append("'").append("\n\tat ");
		for(u_index i=clamp(pos-5,0,reader.arr.length-1),j=clamp(pos+5,0,reader.arr.length);i<=j;i++){
			if(i==pos) sb.append("[POS->");
			if(i>=reader.arr.length) continue;
			char t=reader.arr[i];
			if(t=='\n') sb.append("\\n");
			else sb.append(t);
		}
		int line=1,col=1;
		for(u_index i=0;i<pos;i++){
			if(reader.arr[i]=='\n'){
				line++;
				col=1;
			} else{
				col++;
			}
		}
		sb.append(" (line:").append(line).append(" col:").append(col).append(")");
		return new TokenizeException(sb.toString());
	}*/
	};
}